package genentity;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @desc 根据mysql表字段自动生成java类 根据自己表和路径修改tablename、packageOutPath 两个自定变量
 *       最后需要修改class名
 * @author tao
 *
 */
public class GenEntityMysql {

    private String packageOutPath = "com.bbcare.img.plat.entity";// 指定实体生成所在包的路径
    private String authorName = "******";// 作者名字
    private String tablename[] = new String[] {};// 表名
    private String[] colnames; // 列名数组

    private String[] colTypes; // 列名类型数组
    private String[] colDescs; // 列名类型数组
    private int[] colSizes; // 列名大小数组
    private boolean f_util = false; // 是否需要导入包java.util.*
    private boolean f_sql = false; // 是否需要导入包java.sql.*
    private boolean ts_util = false;// 是否需要导入包import java.sql.Timestamp
    // 数据库连接
    private static final String URL = "jdbc:mysql://rdsap8226j2iuruyoaamgpublic.mysql.rds.aliyuncs.com/test_test";
    private static final String NAME = "zh_xiong";
    private static final String PASS = "xzh123456";
    private static final String DRIVER = "com.mysql.jdbc.Driver";
    private static final String database = "test_test";

    /*
     * 构造函数
     */
    /**
     * @throws SQLException
     */
    public GenEntityMysql() throws SQLException {
        // 创建连接
        Connection con;
        PreparedStatement pStemt = null;
        PreparedStatement pStemt1 = null;
        try {
            Class.forName(DRIVER);
        } catch (ClassNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        con = DriverManager.getConnection(URL, NAME, PASS);
        // 查要生成实体类的表
        String sql = "";
        for (int k = 0; k < tablename.length; k++) {
            sql = "select * from " + tablename[k];

            try {
                // 查找字段
                String sqlname = "select COLUMN_NAME,column_comment from INFORMATION_SCHEMA.Columns where table_name='"
                        + tablename[k] + "' and table_schema='" + database + "';";
                pStemt = con.prepareStatement(sql);
                ResultSetMetaData rsmd = pStemt.getMetaData();

                pStemt1 = con.prepareStatement(sqlname);
                ResultSet rs = pStemt1.executeQuery();
                Map<String, String> map = new HashMap<String, String>();
                while (rs.next()) {
                    String name = rs.getString("COLUMN_NAME");
                    String desc = rs.getString("column_comment");
                    map.put(name.toLowerCase(), desc);
                }

                int size = rsmd.getColumnCount(); // 统计列
                colnames = new String[size];
                colDescs = new String[size];
                colTypes = new String[size];
                colSizes = new int[size];

                for (int i = 0; i < size; i++) {
                    colnames[i] = rsmd.getColumnName(i + 1);
                    colTypes[i] = rsmd.getColumnTypeName(i + 1);
                    String desc = map.get(colnames[i].toLowerCase()) == null ? "" : map.get(colnames[i].toLowerCase());
                    colDescs[i] = desc;
                    if (colTypes[i].equalsIgnoreCase("datetime") || colTypes[i].equalsIgnoreCase("date")) {
                        // f_util = true;
                    }
                    if (colTypes[i].equalsIgnoreCase("timestamp")) {
                        ts_util = true;
                    }

                    if (colTypes[i].equalsIgnoreCase("image") || colTypes[i].equalsIgnoreCase("text")) {
                        f_sql = true;
                    }
                    colSizes[i] = rsmd.getColumnDisplaySize(i + 1);
                }

                String content = parse(colnames, colTypes, colSizes, tablename[k]);

                try {
                    File directory = new File("");
                    System.out.println("绝对路径：" + directory.getAbsolutePath());
                    System.out.println("相对路径：" + directory.getCanonicalPath());

                    String outputPath = directory.getAbsolutePath() + "/src/main/java/"
                            + this.packageOutPath.replace(".", "/") + "/" + initcap(tablename[k]) + ".java";
                    FileWriter fw = new FileWriter(outputPath);
                    PrintWriter pw = new PrintWriter(fw);
                    pw.println(content);
                    pw.flush();
                    pw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                f_util = false; // 是否需要导入包java.util.*
                f_sql = false; // 是否需要导入包java.sql.*
                ts_util = false;// 是否需要导入包import java.sql.Timestamp
            }
        }
    }

    /**
     * 功能：生成实体类主体代码
     * 
     * @param colnames
     * @param colTypes
     * @param colSizes
     * @return
     */
    private String parse(String[] colnames, String[] colTypes, int[] colSizes, String tablename) {
        StringBuffer sb = new StringBuffer();

        // 判断是否导入工具包
        sb.append("package " + this.packageOutPath + ";\r\n");
        if (f_util) {
            sb.append("import java.util.Date;\r\n");
        }
        if (ts_util) {
            sb.append("import java.sql.Timestamp;\r\n");
        }
        if (f_sql) {
            sb.append("import java.sql.*;\r\n");
        }
        sb.append("import java.io.Serializable;\r\n");
        sb.append("import javax.persistence.Entity;\r\n");
        sb.append("\r\n");
        // 注释部分
        sb.append("   /**\r\n");
        sb.append("    * " + tablename + " 实体类\r\n");
        sb.append("    * " + new Date() + " " + this.authorName + "\r\n");
        sb.append("    */ \r\n");
        sb.append("\r\n\r\n@Entity");
        // 实体部分
        sb.append("\r\npublic class " + initcap(tablename) + "  implements Serializable {\r\n");
        sb.append("\tprivate static final long serialVersionUID = 1L;\r\n");
        processAllAttrs(sb);// 属性
        processAllMethod(sb);// get set方法
        sb.append("}\r\n");

        // System.out.println(sb.toString());
        return sb.toString();
    }

    /**
     * 功能：生成所有属性
     * 
     * @param sb
     */
    private void processAllAttrs(StringBuffer sb) {

        for (int i = 0; i < colnames.length; i++) {
            if (!org.springframework.util.StringUtils.isEmpty(colDescs[i])) {
                sb.append("\t//");
                sb.append(colDescs[i]);
                sb.append("\r\n");
            }
            sb.append("\tprivate " + sqlType2JavaType(colTypes[i]) + " " + defineVar(colnames[i]) + ";\r\n");
        }

    }

    /**
     * 功能：将输入字符串的首字母改成大写
     * 
     * @param str
     * @return
     */
    private String initcap(String str) {

        char[] ch = str.toCharArray();
        if (ch[0] >= 'a' && ch[0] <= 'z') {
            ch[0] = (char) (ch[0] - 32);
        }

        return new String(ch);
    }

    /**
     * 功能：获得列的数据类型
     * 
     * @param sqlType
     * @return
     */
    private String sqlType2JavaType(String sqlType) {

        if (sqlType.equalsIgnoreCase("bit")) {
            return "boolean";
        } else if (sqlType.equalsIgnoreCase("tinyint")) {
            return "byte";
        } else if (sqlType.equalsIgnoreCase("smallint")) {
            return "short";
        } else if (sqlType.equalsIgnoreCase("int")) {
            return "Integer";
        } else if (sqlType.equalsIgnoreCase("bigint")) {
            return "Long";
        } else if (sqlType.equalsIgnoreCase("float")) {
            return "float";
        } else if (sqlType.equalsIgnoreCase("decimal") || sqlType.equalsIgnoreCase("numeric")
                || sqlType.equalsIgnoreCase("real") || sqlType.equalsIgnoreCase("money")
                || sqlType.equalsIgnoreCase("smallmoney")) {
            return "double";
        } else if (sqlType.equalsIgnoreCase("varchar") || sqlType.equalsIgnoreCase("char")
                || sqlType.equalsIgnoreCase("nvarchar") || sqlType.equalsIgnoreCase("nchar")
                || sqlType.equalsIgnoreCase("text")) {
            return "String";
        } else if (sqlType.equalsIgnoreCase("datetime")) {
            return "String";
        } else if (sqlType.equalsIgnoreCase("date")) {
            return "String";
        } else if (sqlType.equalsIgnoreCase("image")) {
            return "Blod";
        } else if (sqlType.equalsIgnoreCase("timestamp")) {
            return "String";
        }

        return null;
    }

    /**
     * 功能：生成所有方法
     * 
     * @param sb
     */
    private void processAllMethod(StringBuffer sb) {

        for (int i = 0; i < colnames.length; i++) {
            sb.append("\n\tpublic void set" + transVar(colnames[i]) + "(" + sqlType2JavaType(colTypes[i]) + " "
                    + defineVar(colnames[i]) + "){\r\n");
            sb.append("\t\tthis." + this.defineVar(colnames[i]) + "=" + this.defineVar(colnames[i]) + ";\r\n");
            sb.append("\t}\r\n");
            sb.append("\n\tpublic " + sqlType2JavaType(colTypes[i]) + " get" + transVar(colnames[i]) + "(){\r\n");
            sb.append("\t\treturn " + defineVar(colnames[i]) + ";\r\n");
            sb.append("\t}\r\n");
        }

    }

    /**
     * 用于生成get/set方法时 功能：先将变量字母全变为小写，将第一个字母变为大写，将紧跟“_”后面一个字母大写，并去掉“_”.
     * 
     * @param str
     * @return
     */
    private String transVar(String str) {
        int index = 0;
        if (str.indexOf("_") != -1) {
            index = str.indexOf("_");
            str = str.replace("_", "");
        }
        char[] ch = str.toLowerCase().toCharArray();
        if (ch[0] >= 'a' && ch[0] <= 'z') {
            ch[0] = (char) (ch[0] - 32);
            if (index != 0) {
                ch[index] = (char) (ch[index] - 32);
            }
        }
        str = new String(ch);
        return str;
    }

    /**
     * 用于定义变量名 功能：先将变量字母全变为小写，将紧跟“_”后面一个字母大写，并去掉“_”.
     * 
     * @param str
     * @return
     */
    private String defineVar(String str) {
        int index = 0;
        if (str.indexOf("_") != -1) {
            index = str.indexOf("_");
            str = str.replace("_", "");
        }
        char[] ch = str.toLowerCase().toCharArray();
        if (ch[0] >= 'a' && ch[0] <= 'z' && index != 0) {
            ch[index] = (char) (ch[index] - 32);
        }
        str = new String(ch);
        return str;
    }

    /**
     * 出口 TODO
     * 
     * @param args
     * @throws SQLException
     */
    public static void main(String[] args) throws SQLException {

        new GenEntityMysql();

    }

}
